
import java.util.Vector;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.net.Socket;

public class VerifyService{
	private Vector<Byte> ustobytes(short val){
		Vector<Byte> v = new Vector<Byte>();
		v.clear();

		int n = val;
		if (n < 0){
			n += 0x10000;
		}
		Byte b;
		b = (byte)(n%0x100);
		v.add(b);
		b = (byte)(n/0x100);
		v.add(b);
		return v;
	}
	
	private short bytestous(byte[] bytes){
		int m = bytes[0];
		int n = bytes[1];
		
		if (m < 0){
			m += 0x100;
		}
		if (n < 0){
			n += 0x100;
		}
		
		return (short)(n*0x100+m);
	}
	
	private Vector<Byte> ultobytes(int val){
		Vector<Byte> v = new Vector<Byte>();
		v.clear();
		
		Byte b = (byte)(val%0x100);
		v.add(b);
		b = (byte)((val%0x10000)/0x100);
		v.add(b);
		b = (byte)((val/0x10000)%0x100);
		v.add(b);
		b = (byte)((val/0x10000)/0x100);
		v.add(b);
		return v;
	}
	
	private int bytestoul(byte[] bytes){
		int m = bytes[0];
		int n = bytes[1];
		int x = bytes[2];
		int y = bytes[3];
		
		if (m < 0){
			m += 0x100;
		}
		if (n < 0){
			n += 0x100;
		}
		if (x < 0){
			x += 0x100;
		}
		if (y < 0){
			y += 0x100;
		}
		return n*0x100+m+x*0x10000+y*0x1000000;
	}

	private  Vector<Byte> makePackHead(short packType, 
		byte[] keyData, int dataLen){
		  short check_sum = 0;
		  int i = 0;
		  Vector<Byte> v = new Vector<Byte>();
		  
		  v.clear();
		  v.addAll(ustobytes(packType));

		  v.add(keyData[0]);
		  v.add(keyData[1]);
		  v.add(keyData[2]);
		  v.add(keyData[3]);

		  v.addAll(ultobytes(dataLen));

		  for (i=0; i<v.size(); i++){
			  check_sum +=  v.get(i);
		  }
		  v.addAll(ustobytes(check_sum));
		  return v;
	}
	
	private int parsePackHead(byte[] packHead, short[] packType, 
			byte[] keyData, int[] dataLen){
		short check_sum1 = 0;
		short check_sum2 = 0;
		byte[] tmp = new byte[4];
	
		for (int i=0; i<packHead.length-2; i++){
			int n = packHead[i];
			if (n < 0){
				n += 0x100;
			}
			check_sum1 += n;
		}

		tmp[0] = packHead[packHead.length-2];
		tmp[1] = packHead[packHead.length-1];
		check_sum2 = bytestous(tmp);
		if (check_sum2 != check_sum1){
		    return -1;
		}

		tmp[0] = packHead[0];
		tmp[1] = packHead[1];
		packType[0] = bytestous(tmp);
		
		keyData[0] = packHead[2];
		keyData[1] = packHead[3];
		keyData[2] = packHead[4];
		keyData[3] = packHead[5];
		
		tmp[0] = packHead[6];
		tmp[1] = packHead[7];
		tmp[2] = packHead[8];
		tmp[3] = packHead[9];
		dataLen[0] = bytestoul(tmp);
		return 0;
	}
	
	private byte[] makePacket(short packType, Vector<Byte> data){
		Vector<Byte> v = new Vector<Byte>();
		v.clear();
		
		byte[] keyData = new byte[4];
		keyData[0] = 0;
		keyData[1] = 0;
		keyData[2] = 0;
		keyData[3] = 0;
		
		v.addAll(makePackHead(packType, keyData, data.size()+2));
		v.addAll(data);
		short checkSum = 0;
		for (int i=0; i<data.size(); i++){
			checkSum += data.get(i);
		}
		v.addAll(ultobytes(checkSum));
		
		byte b[] = new byte[v.size()];
		for (int i=0; i<v.size(); i++){
			b[i] = v.get(i);
		}
		return b;
	}
	
	protected Vector<Byte> MakeField(String value){
		Vector<Byte> v = new Vector<Byte>();
		
		v.addAll(ustobytes((short)value.length()));
		byte[] b = value.getBytes();
		for (int i=0; i<b.length; i++){
			v.add(b[i]);
		}
		return v;
	}
	
	private String serverIp;
	private int serverPort;
	private int exeCommand(){
		try{
			InetSocketAddress addr = new InetSocketAddress(
					serverIp, serverPort);
			Socket sock = new Socket();
			sock.connect(addr, 3000);
			OutputStream out = sock.getOutputStream();
			out.write(makePacket(FUNC_REQ_VERIFY_CLERK, MakePackBody()));
			
			InputStream in = sock.getInputStream();			
			byte[] packHead = new byte[12];
			if (in.read(packHead) != packHead.length){
				sock.close();
				return -1;
			}
						
			short[] recvpackType = new short[1];
			byte[] keyData = new byte[4];
			int[] dataLen = new int[1];
			
			int result = parsePackHead(packHead, recvpackType, 
					keyData, dataLen);
			if (result != 0){
				return -2;
			}
						
			if (FUNC_RET_VERIFY_CLERK != recvpackType[0]){
				return -3;
			}

			byte[] data = new byte[dataLen[0]];
			if (in.read(data) != dataLen[0]){
				return -4;
			}
			
			result = bytestous(data);
			sock.close();
			
			return result;
		}
		catch (IOException e){
			return -100;
		}
	}

	private String flag;
	private String sysno;
	private String deptno;
	private String clerkno;
	private String vendor;
	private String finger;
	private String transno;

	private static final short FUNC_REQ_VERIFY_CLERK=19;
	private static final short FUNC_RET_VERIFY_CLERK=8019;
	
	private static final short ERROR_OK = 0;
	private static final short ERROR_OPER_NOT_EXIST = 6002;
	private static final short ERROR_FINGER_MISMATCH = 6003;
	private static final short ERROR_DEPT_NOT_EXIST = 6004;

	private VerifyService(String serverIp, int serverPort,
			int flag, int sysno, String deptno, String clerkno, 
			String vendor, String finger, String transno){ 
		this.serverIp = serverIp;
		this.serverPort = serverPort;
		this.flag = String.valueOf(flag);
		this.sysno = String.valueOf(sysno);
		this.deptno = deptno;
		this.clerkno = clerkno;
		this.vendor = vendor;
		this.finger = finger;
		this.transno = transno;
	}

	private Vector<Byte> MakePackBody() {
		Vector<Byte> data = new Vector<Byte>();
		data.clear();
		data.addAll(MakeField(flag));
		data.addAll(MakeField(sysno));
		data.addAll(MakeField(deptno));
		data.addAll(MakeField(clerkno));
		data.addAll(MakeField(vendor));
		data.addAll(MakeField(finger));
		data.addAll(MakeField(transno));
		return data;
	}

	public static int verifyClerk(String serverIp, int serverPort,
			int flag, int sysno, String deptno, String clerkno,
			String finger, String transno){
		VerifyService obj = new VerifyService(serverIp, serverPort, 
				flag, sysno, deptno, clerkno, "1", finger, transno);
		int result = obj.exeCommand();
		switch (result){
			case ERROR_OK:
				return 0;
			case ERROR_FINGER_MISMATCH:
				return 1;
			case ERROR_OPER_NOT_EXIST:
				return 2;
			case ERROR_DEPT_NOT_EXIST:
				return 3;
			default:
				return -1;
		}
	}

	public static void main(String[] args){
		for (int i=0; i<100; i++){
		int result = verifyClerk("139.3.0.86", 7000, 0, 1, "0001", "000001", "", "8888");
		System.out.println("result="+result);
		}
	}
}
